Skip to content

fix(qn-scale): support store-and-forward variants that deliver 0x23 records#233

Open
built-dev wants to merge 1 commit into
KristianP26:devfrom
built-dev:fix/qn-store-and-forward
Open

fix(qn-scale): support store-and-forward variants that deliver 0x23 records#233
built-dev wants to merge 1 commit into
KristianP26:devfrom
built-dev:fix/qn-store-and-forward

Conversation

@built-dev

Copy link
Copy Markdown

Problem

Some QN-protocol Renpho units never stream live 0x10 weight frames. Confirmed on a real Renpho Elis 1 (advertises as Renpho-Scale, FFF0 + AE00 services, 18-byte 0x12 scale info with factor=10): the scale measures autonomously, stores the finished measurement, and delivers it as a 0x23 record right after the handshake completes. Since the adapter ignores 0x23 ("historical record, no action needed"), every session ends in Scale disconnected before reading completed and the scale produces no readings at all.

There's a second wrinkle: an always-on listener connects the moment the scale wakes (it only advertises when stepped on), i.e. mid-measurement — at which point the scale reports an empty history and never volunteers the fresh record on its own.

Observed 0x23 layout (19 bytes, captured from hardware)

bytes meaning
[3] total record count (00 = empty "no records" frame)
[4] record index, 1-based
[6-9] measurement timestamp, LE, seconds since 2000-01-01
[10-11] weight, BE, factor-scaled (existing alternate-factor heuristic applies)
[12-13] / [14-15] R1 / R2 BIA resistances

Example real frame: 23 13 ff 01 01 f0 aa c9 bd 31 1e 5a 01 f1 01 ef 00 00 e2 → 77.7 kg, R1=497.

Fix

  1. Parse 0x23 records as readings, deduplicating replays across reconnects via the record's scale-side timestamp.
  2. Nudge for the fresh record: when the history is empty (connected mid-measurement), re-send the 0x22 start command every 5 s (max 12×). The scale then delivers the new record in-session — typically by the third nudge, ~15–20 s after step-on. Timer is cleaned up on reconnect/record/write-failure and never starts without an active connection.

Live 0x10 parsing is untouched; scales that stream normally behave exactly as before (0x23 empty frames merely arm the nudge, and a delivered 0x10 reading was already terminal).

Testing

  • 6 new Vitest cases for the 0x23 path (real-capture frame, factor heuristic, multi-record session, empty terminator, replay dedup, R2 fallback) in the existing qn-scale.test.ts style.
  • Full suite: 1630/1630 passing, tsc --noEmit and eslint clean.
  • Hardware-verified end-to-end (Linux/BlueZ via node-ble, continuous mode): previously zero readings; with this change every weigh-in lands whether the connection happens before, during, or after the measurement.

This may explain other "connects fine but 'disconnected before reading completed'" reports on Renpho/QN units.

🤖 Generated with Claude Code

…ecords

Some QN-protocol Renpho units (confirmed on a real Elis 1 advertising as
'Renpho-Scale') never stream live 0x10 weight frames. The scale measures
on its own, stores the finished measurement, and delivers it as a 0x23
record right after the handshake — frames the adapter previously ignored
('historical record, no action needed'). Every session ended in
'Scale disconnected before reading completed' with zero readings.

Observed 19-byte 0x23 layout (captured from hardware):
  [3]     total record count (00 = empty 'no more records' frame)
  [4]     record index, 1-based
  [6-9]   measurement timestamp (LE, seconds since 2000-01-01)
  [10-11] weight (BE, factor-scaled; alternate-factor heuristic applies)
  [12-13] R1, [14-15] R2 (BIA resistances)

Two changes:
- parse 0x23 records as readings, with a timestamp set to dedup replays
  across reconnects
- when the history is empty (we connected mid-measurement, so the
  in-progress reading is not stored yet), re-send the 0x22 start command
  every 5s (max 12x); the scale then delivers the fresh record
  in-session — typically by the third nudge, ~15-20s after step-on

Verified end-to-end on hardware: previously zero readings; with this
change every weigh-in lands, whether the connection happens before,
during, or after the measurement.
@KristianP26 KristianP26 self-requested a review June 12, 2026 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant